﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Configuration.ServerApi.Common
{
    /// <summary>
    /// ChatHub
    /// </summary>
    public class ChatHub : Hub
    {
        #region 公共变量

        // private readonly ImfusRepository<MfusSysUser> _CUser;我的用户接口
        // private readonly IAuthService _authService;  授权接口

        private IMemoryCache _mcache;
        private const string ModelKey = "my.Hub.list";
        private const string DefGroup = "my.DefGroup";

        /// <summary>
        /// user
        /// </summary>
        public LoginUser user { get; set; }

        #endregion

        #region 构造函数

        /// <summary>
        /// ChatHub
        /// </summary>
        /// <param name="httpContextAccessor"></param>
        /// <param name="mcache"></param>
        public ChatHub(//ImfusRepository<MfusSysUser> CUser,
             IHttpContextAccessor httpContextAccessor,
             IMemoryCache mcache
        //IAuthService authService
        )
        {
            //_authService = authService;
            _mcache = mcache;
            // _CUser = CUser;
        }

        #endregion

        #region OnConnectedAsync

        /// <summary>
        /// OnConnectedAsync 启动异步连接
        /// 
        /// (如果有新的连接建立了, 这个方法就会被执行.)
        /// </summary>
        /// <returns></returns>
        public override async Task OnConnectedAsync()
        {
            // 获取链接客户端唯一ID
            var connectionid = Context.ConnectionId;
            Console.WriteLine($"Connectionid：{connectionid}");

            // 使用ConnectionId, 我们就可以取得这个客户端, 并调用其方法,
            await Clients.Client(connectionid).SendAsync("Show", new { name = "欢迎进入中小微企业危废全生命周期大数据分析中心" });

            // AllExcept(connectionId)就是除了这个connectionId的客户端之外的所有客户端
            //await Clients.AllExcept(connectionid).SendAsync("Show");

            // 删除一个名字叫Mygroups组里面的 connectionid这个客户端
            //await Groups.RemoveFromGroupAsync(connectionid, "Mygroups");

            // 根据组发送信息
            //await Clients.Group("Mygroups").SendAsync("Show");
        }

        #endregion

        #region OnDisconnectedAsync

        /// <summary>
        /// OnDisconnectedAsync 断开异步连接
        /// </summary>
        /// <param name="exception"></param>
        /// <returns></returns>
        public override async Task OnDisconnectedAsync(Exception exception)
        {
            List<ThisCidOrUid> thisCidOrUids = null;

            _mcache.TryGetValue(ModelKey, out thisCidOrUids);
            if (thisCidOrUids != null)
            {
                var context = thisCidOrUids.Where(x => x.Cid == Context.ConnectionId).FirstOrDefault();
                thisCidOrUids.Remove(context);
                _mcache.Set(ModelKey, thisCidOrUids, DateTimeOffset.Now.AddDays(1));
            }

            await Clients.GroupExcept("Mygroups", Context.ConnectionId).SendAsync("Show", new { Name = $"用户退出了系统!, 退出时间: {DateTime.Now}" });
            await Groups.RemoveFromGroupAsync(Context.ConnectionId, "");
        }

        #endregion

        #region BinduidAsync

        /// <summary>
        /// BinduidAsync
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public async Task<Rentity> BinduidAsync(string uid)
        {
            //user = await _authService.GetloginAsync(uid);

            List<ThisCidOrUid> thisCidOrUids;
            _mcache.TryGetValue(ModelKey, out thisCidOrUids);
            if (thisCidOrUids == null)
            {
                List<ThisCidOrUid> uids = new List<ThisCidOrUid>() { new ThisCidOrUid() { Cid = Context.ConnectionId, Uid = uid } };
                _mcache.Set(ModelKey, uids, DateTimeOffset.Now.AddDays(1));
            }
            else
            {
                thisCidOrUids.Add(new ThisCidOrUid() { Cid = Context.ConnectionId, Uid = uid });
                _mcache.Set(ModelKey, thisCidOrUids, DateTimeOffset.Now.AddDays(1));
            }

            // user =await  _CUser.Table.Where(x => x.Id == uid).FirstOrDefaultAsync();
            //if (user == null)
            //    ME.Msg("没有找到用户");

            string groupName = string.IsNullOrEmpty(user.AppId) ? DefGroup : user.AppId;

            //创建一个名字叫 Mygroups组
            await Groups.AddToGroupAsync(Context.ConnectionId, groupName);

            await Clients.GroupExcept(groupName, Context.ConnectionId).SendAsync("Show", new { Name = $"用户: {user.UserName} 登陆了系统!!\n登陆时间: {DateTime.Now:yyyy-MM-dd hh:mm:ss}" });
            //await Clients.All.SendAsync("Show", new { user.Name });

            return new Rentity { Code = 0, Msg = "用户连接成功" };
        }

        #endregion

        #region SendMsg

        /// <summary>
        /// SendMsg
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public Task SendMsg(ChatMessageInfo info)
        {
            // 这里的Show代表是客户端的方法，具体可以细看SignalR的说明
            return Clients.All.SendAsync("Show", info.UserName + ":" + info.Message);
        }

        #endregion

        #region SendMsgTest

        /// <summary>
        /// SendMsgTest
        /// </summary>
        /// <param name="json">此处我传入的json字符串,可根据自己需求修改</param>
        /// <returns></returns>
        public Task SendMsgTest(string json)
        {
            JObject jObj = JObject.Parse(json);

            // 通过属性名或者索引来访问，仅仅是自己的属性名，而不是所有的
            JToken UserNameToken = jObj["UserName"];
            JToken MessageToken = jObj["Message"];

            // 在客户端实现此处的Show方法
            return Clients.All.SendAsync("Show", UserNameToken.ToString() + ":" + MessageToken.ToString());
        }

        #endregion

    }

    #region ChatMessageInfo

    /// <summary>
    /// ChatMessageInfo
    /// </summary>
    public class ChatMessageInfo
    {
        /// <summary>
        /// UserName
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        /// Message
        /// </summary>
        public string Message { get; set; }
    }

    #endregion

    #region LoginUser

    /// <summary>
    /// LoginUser
    /// </summary>
    public class LoginUser
    {
        /// <summary>
        /// AppId
        /// </summary>
        public string AppId { get; set; }

        /// <summary>
        /// UserName
        /// </summary>
        public string UserName { get; set; }
    }

    #endregion

    #region Rentity

    /// <summary>
    /// Rentity
    /// </summary>
    public class Rentity
    {
        /// <summary>
        /// Code
        /// </summary>
        public int Code { get; set; }

        /// <summary>
        /// Msg
        /// </summary>
        public string Msg { get; set; }
    }

    #endregion

    #region ThisCidOrUid

    /// <summary>
    /// ThisCidOrUid
    /// </summary>
    public class ThisCidOrUid
    {
        /// <summary>
        /// Cid
        /// </summary>
        public string Cid { get; set; }

        /// <summary>
        /// Uid
        /// </summary>
        public string Uid { get; set; }
    }

    #endregion

}
